
/**
 * 订阅发布
 *
 * @param {*} isPublish 是否订阅及时发布
 */
export = class Publisher {

  subscribers: any = {}
  publishers: any = {}
  constructor(public isPublish = true) { }
  /**
   * type: 类型， key: 订阅key值, obj：function/data, mode: 方式：once订阅一次
   * @param {*} type 类型
   * @param {*} key eventkey
   * @param {*} obj 方法
   * @param {*} mode  方式
   */
  visitSubscribers(type: any, key: string, obj: any, mode?: string) {
    if (type === 'unsubscribe') {
      if (!obj) this.subscribers[key] = void 0
      else {
        for (let i = 0; i < this.subscribers[key].fn; i++) {
          if (obj === this.subscribers[key].fu[i]) return this.subscribers[key].fu.splice(i, 1)
        }
      }
      return
    }
    var keys = key.split(',')
    for (let i = 0; i < keys.length; i++) {
      key = keys[i].trim();
      if (key === '') continue
      if (!this.subscribers[key]) this.subscribers[key] = { fn: [] }
      if (type === 'subscribe') {
        if (mode) {
          obj = {
            mode: mode,
            fn: obj
          }
        }
        this.subscribers[key].fn.push(obj)
      }
      if (type === 'publish') {
        this.subscribers[key].data = obj
      }

      if (!this.isPublish && type !== 'publish') return;

      if (this.subscribers[key].data) {
        // 要移除的fn
        var delIndex = []
        for (let i = 0; i < this.subscribers[key].fn.length; i++) {
          var fn = this.subscribers[key].fn[i]
          if (typeof fn == "function") fn(this.subscribers[key].data[0], this.subscribers[key].data[1], this.subscribers[key].is)
          else if (fn.mode === 'once') {
            delIndex.push(i)
            fn.fn(this.subscribers[key].data[0], this.subscribers[key].data[1], this.subscribers[key].is)
          }
        }
        for (let j in this.publishers) {
          this.publishers[j].publish(key, this.subscribers[key].data[0], this.subscribers[key].data[1])
        }
        delIndex.forEach(function (i, val) {
          this.subscribers[key].fn.splice(val, 1)
        })
        this.subscribers[key].is = true
      }
    }
  }
  /**
   * 取消订阅事件
   * @param {*} key eventkey
   * @param {*} fn 订阅方法
   */
  unsubscribe(key: string, fn: any) {
    if (!this.subscribers[key]) return
    this.visitSubscribers('unsubscribe', key, fn)
  }

  /**
   * 订阅事件
   * @param {*} key eventkey
   * @param {*} fn 订阅方法
   */
  subscribe(key: string, fn: any) {
    var keys = key.split(':')
    this.visitSubscribers('subscribe', keys[0], fn, keys[1])
  }
  /**
   * 发布内容
   * @param {*} key eventkey
   * @param {*} data 数据
   */
  publish(key: string, data: any, config: any) {
    this.visitSubscribers('publish', key, [data, config])
  }
  /**
   * 清楚订阅事件
   */
  clear() {
    this.subscribers = {}
  }


  /**
   * namespace
   *
   * @param {*} key
   * @param {boolean} [isPublish]
   * @returns
   */
  namespace(key: any, isPublish?: boolean) {
    this.publishers[key] = new Publisher(isPublish)
    return this.publishers[key];
  }
}
